浅析微信支付:申请退款、退款回调接口、查询退款

本文是【浅析微信支付】系列文章的第八篇,主要讲解商户如何处理微信申请退款、退款回调、查询退款接口,其中有一些坑的地方,会着重强调。


浅析微信支付系列已经更新七篇了哟~,没有看过的朋友们可以看一下哦。

浅析微信支付:查询订单和关闭订单

浅析微信支付:支付结果通知

浅析微信支付:统一下单接口

在实际场景中,申请退款和退款回调接口是比较常用到的微信支付接口,这里我们会讲原路返回方式的退款,还有的是使用直接为用户付款到零钱现金红包等方式来退款,此种情况主要会出现在客服退款时,不是全部退款的情况,也有的会出现在使用了微信代金券-单品券的时候,因为单品券不能部分退款,所以只能走企业付款用户的方式,以下我们主要讲原路返回退款。

PS:原路返回的意思就是,从你支付时的关联支付单中扣款,微信会记录相关数据,可以在客户端通知中展示。

1、申请退款接口

以下为微信官方的申请退款文档:

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4

1.1. 应用场景

当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。

注意:
1、交易时间超过一年的订单无法提交退款
2、微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。 一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号
3、请求频率限制:150qps,即每秒钟正常的申请退款请求次数不超过150次
错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次
4、每个支付订单的部分退款次数不能超过50次

PS:以上限制一般情况下不会出现,但我们也必须写入系统异常场景处理中,请求频率可以使用队列或增加延迟等方式来处理,部分退款此时不要超过微信的限制。

1.2. 接口链接

https://api.mch.weixin.qq.com/secapi/pay/refund

1.3. 是否需要证书

请求需要双向证书。

PS:关于微信证书,可以在 [商户平台-账户中心-API安全] 去下载,此证书很多支付接口均需要使用,请将证书地址配置为常量,具体实现可以参考作者github源码。

1.4. 调用接口

先看源码,如下:

/*** [微信退款接口] - 保存调用的相关记录* @param refundPayment 退款订单的支付记录* @param tradePayment 历史付款单* @return map* @throws Exception e** @author yclimb* @date 2018/6/21*/
public Map<String,String> saveWxPayRefund(Payment refundPayment, Payment tradePayment) throws Exception {if (refundPayment == null || tradePayment == null) {return null;}// 微信订单号/商户订单号,必须传入其中一个,此处默认传入商户订单号// 微信订单号,微信生成的订单号,在支付通知中有返回// String transaction_id = null;// 商户订单号,商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。String out_trade_no = tradePayment.getFlowNumer();// 商户退款单号,商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。String out_refund_no = refundPayment.getFlowNumer();// 订单总金额,传入参数单位为:元String total_fee = String.valueOf(tradePayment.getAmount());// 退款总金额,订单总金额,传入参数单位为:元String refund_fee = String.valueOf(refundPayment.getAmount());// 退款原因,若商户传入,会在下发给用户的退款消息中体现退款原因String refund_desc = refundPayment.getBody();// 微信支付对象WXPay wxPay = new WXPay(WXPayConfigImpl.getInstance());// 微信退款接口Map<String, String> resultMap = wxPay.refund(refundUrl, null, out_trade_no, out_refund_no, total_fee, refund_fee, refund_desc);logger.info("saveWxPayRefund:resultMap:" + resultMap.toString());// 记录付款流水// 下单失败,进行处理if (WXPayConstants.FAIL.equals(resultMap.get(WXPayConstants.RETURN_CODE)) ||WXPayConstants.FAIL.equals(resultMap.get(WXPayConstants.RESULT_CODE))) {// 处理结果返回,无需继续执行resultMap.put(WXPayConstants.RESULT_CODE, WXPayConstants.FAIL);resultMap.put(WXPayConstants.ERR_CODE_DES, resultMap.get(WXPayConstants.RETURN_MSG));return resultMap;}return resultMap;
}

以上为sdk退款调用示例代码,有几个参数需要我们注意:

字段名变量名必填类型描述
微信订单号transaction_idString(32)微信生成的订单号,在支付通知中有返回
商户订单号out_trade_noString(32)商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-
商户退款单号out_refund_noString(64)商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-
退款金额refund_feeInt退款总金额,订单总金额,单位为分,只能为整数
退款结果通知urlnotify_urlString(256)异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数,如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。

PS:推荐以上的参数都必填,notify_url参数可配置为环境常量,根据环境的不同配置调用不会的回调地址。

下面为具体的实际sdkwxPay.refund调用代码:

/*** 作用:申请退款<br>* 场景:当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,* 微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。* 接口文档地址:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_4** @param notify_url     回调地址* @param transaction_id 微信生成的订单号,在支付通知中有返回* @param out_trade_no   商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。* @param out_refund_no  商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。* @param total_fee      订单总金额,传入参数单位为:元* @param refund_fee     退款总金额,订单总金额,传入参数单位为:元* @param refund_desc    退款原因,若商户传入,会在下发给用户的退款消息中体现退款原因* @return API返回数据* @throws Exception e*/
public Map<String, String> refund(String notify_url, String transaction_id, String out_trade_no, String out_refund_no,String total_fee, String refund_fee, String refund_desc) throws Exception {/** 构造请求参数数据 **/Map<String, String> data = new HashMap<>();// 变量名      字段名 必填  类型  示例值 描述// 微信订单号    二选一 String(32)  1.21775E+27 微信生成的订单号,在支付通知中有返回if (transaction_id != null) {data.put("transaction_id", transaction_id);}// 商户订单号    String(32)  1.21775E+27 商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。data.put("out_trade_no", out_trade_no);// 商户退款单号   是   String(64)  1.21775E+27 商户系统内部的退款单号,商户系统内部唯一,只能是数字、大小写字母_-|*@ ,同一退款单号多次请求只退一笔。data.put("out_refund_no", out_refund_no);// 订单金额 是   Int 100 订单总金额,单位为分,只能为整数,详见支付金额data.put("total_fee", String.valueOf(new BigDecimal(total_fee).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue()));// 退款金额 是   Int 100 退款总金额,订单总金额,单位为分,只能为整数,详见支付金额// 默认单位为分,系统是元,所以需要*100data.put("refund_fee", String.valueOf(new BigDecimal(refund_fee).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue()));// 退款原因 否   String(80)  商品已售完   若商户传入,会在下发给用户的退款消息中体现退款原因data.put("refund_desc", refund_desc);// 货币种类 否   String(8)   CNY 货币类型,符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型data.put("refund_fee_type", WXPayConstants.FEE_TYPE_CNY);// 退款结果通知url    否   String(256) https://weixin.qq.com/notify/   异步接收微信支付退款结果通知的回调地址,通知URL必须为外网可访问的url,不允许带参数,如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。data.put("notify_url", notify_url);/** 以下参数为非必填参数 **/// 退款资金来源   否   String(30)  REFUND_SOURCE_RECHARGE_FUNDS    仅针对老资金流商户使用;REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款(默认使用未结算资金退款);REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款// data.put("refund_account", null);/** 以下五个参数,在 this.fillRequestData 方法中会自动赋值 **//*// 小程序ID  appid   是   String(32)  wxd678efh567hg6787  微信分配的小程序IDdata.put("appid", WXPayConstants.APP_ID);// 商户号  mch_id  是   String(32)  1230000109  微信支付分配的商户号data.put("mch_id", WXPayConstants.MCH_ID);// 随机字符串    nonce_str   是   String(32)  5K8264ILTKCH16CQ2502SI8ZNMTM67VS    随机字符串,长度要求在32位以内。推荐随机数生成算法data.put("nonce_str", nonce_str);// 签名类型 sign_type   否   String(32)  MD5 签名类型,默认为MD5,支持HMAC-SHA256和MD5。data.put("sign_type", WXPayConstants.MD5);// 签名   sign    是   String(32)  C380BEC2BFD727A4B6845133519F3AD6    通过签名算法计算得出的签名值,详见签名生成算法data.put("sign", sign);*/// 微信退款接口Map<String, String> resultMap = this.refund(data);WXPayUtil.getLogger().info("wxPay.refund:" + resultMap);return resultMap;
}

以上已经详细说明的具体的字段含义,有不明白的同学可以查看微信的官方文档,具体的源码可以查看作者的github。

这里有一个比较需要注意的点,在我们调用退款之后,会返回一些异常处理情况,官方文档中收录了一系列错误码code,我们可以在系统中对其进行处理,这里就不细说了。

2、退款回调接口

以下为微信官方的退款结果通知文档:

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_16&index=10

2.1. 应用场景

当商户申请的退款有结果后,微信会把相关结果发送给商户,商户需要接收处理,并返回应答。
对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。

(通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)

注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。
推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。

特别说明:退款结果对重要的数据进行了加密,商户需要用商户秘钥进行解密后才能获得结果通知的内容

2.2. 接口链接

在申请退款接口中上传参数“notify_url”以开通该功能
如果链接无法访问,商户将无法接收到微信通知。
通知url必须为直接可访问的url,不能携带参数。

示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”

2.3. 解密方式

解密步骤如下: 
(1)对加密串A做base64解码,得到加密串B
(2)对商户key做md5,得到32位小写key* ( key设置路径:微信商户平台-->账户设置-->API安全-->密钥设置 )
(3)用key*对加密串B做AES-256-ECB解密(PKCS7Padding)

PS:特别注意,如果要进行微信AES解密,因为GJ的进口管制限制,Java发布的运行环境包中的加解密有一定的限制。默认不允许256位密钥的AES加解密,解决方法就是修改策略文件,我们需要从官方网站下载无限制权限策略文件,注意自己JDK的版本别下错了。

jdk8的jce下载地址:https://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html

将local_policy.jar和US_export_policy.jar这两个文件替换%JRE_HOME%\lib\security和%JDK_HOME%\jre\lib\security下原来的文件,注意先备份原文件。

如果是jdk8,可能会遇到安全目录下有policy文件夹的情况,拿作者的电脑举例,jdk路径为/opt/jdk1.8.0_152/jre/lib/security/policy,此目录下有两个子文件夹limitedlimited,需要替换limited文件夹下的文件 local_policy.jarUS_export_policy.jar这两个,最好先备份哦~!!!替换后重启项目即可。

2.4. 调用接口

因为退款回调接口是咋们系统被动接收微信的消息,所以此处和支付回调接口一致,也是使用了流的方式,格式为xml,下面我们来看代码:


/*** 退款结果通知* <p>* 在申请退款接口中上传参数“notify_url”以开通该功能* 如果链接无法访问,商户将无法接收到微信通知。* 通知url必须为直接可访问的url,不能携带参数。示例:notify_url:“https://pay.weixin.qq.com/wxpay/pay.action”* <p>* 当商户申请的退款有结果后,微信会把相关结果发送给商户,商户需要接收处理,并返回应答。* 对后台通知交互时,如果微信收到商户的应答不是成功或超时,微信认为通知失败,微信会通过一定的策略定期重新发起通知,尽可能提高通知的成功率,但微信不保证通知最终能成功。* (通知频率为15/15/30/180/1800/1800/1800/1800/3600,单位:秒)* 注意:同样的通知可能会多次发送给商户系统。商户系统必须能够正确处理重复的通知。* 推荐的做法是,当收到通知进行处理时,首先检查对应业务数据的状态,判断该通知是否已经处理过,如果没有处理过再进行处理,如果处理过直接返回结果成功。在对业务数据进行状态检查和处理之前,要采用数据锁进行并发控制,以避免函数重入造成的数据混乱。* 特别说明:退款结果对重要的数据进行了加密,商户需要用商户秘钥进行解密后才能获得结果通知的内容* @param request req* @param response resp* @return res xml** @author yclimb* @date 2018/6/21*/
@ApiOperation(value = "微信支付|微信退款回调接口", httpMethod = "POST", notes = "该链接是通过【微信退款API】中提交的参数notify_url设置,如果参数中传了notify_url,则商户平台上配置的回调地址将不会生效。")
@RequestMapping("/refund")
public void refund(HttpServletRequest request, HttpServletResponse response) {String resXml = "";InputStream inStream;try {inStream = request.getInputStream();ByteArrayOutputStream outSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inStream.read(buffer)) != -1) {outSteam.write(buffer, 0, len);}WXPayUtil.getLogger().info("refund:微信退款----start----");// 获取微信调用我们notify_url的返回信息String result = new String(outSteam.toByteArray(), "utf-8");WXPayUtil.getLogger().info("refund:微信退款----result----=" + result);// 关闭流outSteam.close();inStream.close();// xml转换为mapMap<String, String> map = WXPayUtil.xmlToMap(result);if (WXPayConstants.SUCCESS.equalsIgnoreCase(map.get(WXPayConstants.RETURN_CODE))) {WXPayUtil.getLogger().info("refund:微信退款----返回成功");/** 以下字段在return_code为SUCCESS的时候有返回: **/// 加密信息:加密信息请用商户秘钥进行解密,详见解密方式String req_info = map.get("req_info");/*** 解密方式* 解密步骤如下:* (1)对加密串A做base64解码,得到加密串B* (2)对商户key做md5,得到32位小写key* ( key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置 )* (3)用key*对加密串B做AES-256-ECB解密(PKCS7Padding)*/String resultStr = AESUtil.decryptData(req_info);// WXPayUtil.getLogger().info("refund:解密后的字符串:" + resultStr);Map<String, String> aesMap = WXPayUtil.xmlToMap(resultStr);/** 以下为返回的加密字段: **///  商户退款单号  是   String(64)  1.21775E+27 商户退款单号String out_refund_no = aesMap.get("out_refund_no");//  退款状态    是   String(16)  SUCCESS SUCCESS-退款成功、CHANGE-退款异常、REFUNDCLOSE—退款关闭String refund_status = aesMap.get("refund_status");//  商户订单号   是   String(32)  1.21775E+27 商户系统内部的订单号String out_trade_no = aesMap.get("out_trade_no");/*//    微信订单号   是   String(32)  1.21775E+27 微信订单号String transaction_id = null;//  微信退款单号  是   String(32)  1.21775E+27 微信退款单号String refund_id = null;//  订单金额    是   Int 100 订单总金额,单位为分,只能为整数,详见支付金额String total_fee = null;//  应结订单金额  否   Int 100 当该订单有使用非充值券时,返回此字段。应结订单金额=订单金额-非充值代金券金额,应结订单金额<=订单金额。String settlement_total_fee = null;//  申请退款金额  是   Int 100 退款总金额,单位为分String refund_fee = null;//  退款金额    是   Int 100 退款金额=申请退款金额-非充值代金券退款金额,退款金额<=申请退款金额String settlement_refund_fee = null;*/// 退款是否成功if (!WXPayConstants.SUCCESS.equals(refund_status)) {resXml = resFailXml;} else {// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.resXml = resSuccessXml;isSuccess = true;}// 根据付款单号查询付款记录 out_refund_no// 付款记录修改 & 记录付款日志if (payment != null) {WXPayUtil.getLogger().error("refund:微信支付回调:修改支付单");} else {WXPayUtil.getLogger().error("refund:微信支付回调:找不到对应的支付单");}} else {WXPayUtil.getLogger().error("refund:支付失败,错误信息:" + map.get(WXPayConstants.RETURN_MSG));resXml = resFailXml;}} catch (Exception e) {WXPayUtil.getLogger().error("refund:微信退款回调发布异常:", e);} finally {try {// 处理业务完毕BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());out.write(resXml.getBytes());out.flush();out.close();} catch (IOException e) {WXPayUtil.getLogger().error("refund:微信退款回调发布异常:out:", e);}}
}

以上代码详细解释了如何接收微信回调数据和解码数据,具体的AESUtil.decryptData(req_info)请参考作者源码,文末有地址,这里就不细讲了。

具体的退款接收参数请参考微信官方文档,需要注意的是商户退款单号微信退款单号,此两个参数是修改和记录退款的必要凭证。

3、查询退款

以下为微信官方的查询退款文档:

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5

3.1. 应用场景

提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。

注意:如果单个支付订单部分退款次数超过20次请使用退款单号查询

3.2. 接口链接

https://api.mch.weixin.qq.com/pay/refundquery

3.3. 是否需要证书

不需要

3.4. 调用接口

注意:当一个订单部分退款超过10笔后,商户用微信订单号或商户订单号调退款查询API查询退款时,默认返回前10笔和total_refund_count(订单总退款次数)。商户需要查询同一订单下超过10笔的退款单时,可传入订单号及offset来查询,微信支付会返回offset及后面的10笔,以此类推。当商户传入的offset超过total_refund_count,则系统会返回报错PARAM_ERROR

举例:

一笔订单下的退款单有36笔,当商户想查询第25笔时,可传入订单号及offset=24,微信支付平台会返回第25笔到第35笔的退款单信息,或商户可直接传入退款单号查询退款

以下为调用方式:

private void doRefundQuery() {// 四选一,微信订单号查询的优先级是: refund_id > out_refund_no > transaction_id > out_trade_noHashMap<String, String> data = new HashMap<String, String>();// 商户订单号data.put("out_trade_no", out_trade_no);// 微信订单号data.put("transaction_id", out_trade_no);// 商户退款单号   data.put("out_refund_no", out_trade_no);// 微信退款单号   data.put("refund_id", out_trade_no);try {Map<String, String> r = wxpay.refundQuery(data);System.out.println(r);} catch (Exception e) {e.printStackTrace();}
}

PS:微信订单号查询的优先级是: refund_id > out_refund_no > transaction_id > out_trade_no

需要注意的是,查询退款时,需要注意退款返回的错误码,如果出现错误,需要及时同步商户系统中的退款数据。

结语

以上为申请退款、退款回调接口、查询退款相关的解释和源码,特别需要注意的是接收退款时的解密方式和替换安全文件,小伙伴们一定要注意哦,具体的源码可以看作者的github,里面对每个方法有详细的注释。

预告:下一篇文章 下载对账单和资金账单,敬请期待!!!

​如果想要提前一览源码的小伙伴,可以先看看我的 github,地址如下:

​https://github.com/YClimb/wxpay-sdk/blob/master/README.md ​

加作者私人微信,作者微信号如下 yclimb,标明 微信支付 可拉入微信支付讨论群与小伙伴一起探讨哦,一定要标明 微信支付 哦~

到此本文就结束了,关注公众号查看更多推送!!!


关注我的公众号


转载于:https://www.cnblogs.com/yclimb/p/9934046.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/389154.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

view工作原理-计算视图大小的过程(onMeasure)

view的视图有两种情况&#xff1a; 内容型视图&#xff1a;由视图的内容决定其大小。图形型视图&#xff1a;父视图为view动态调整大小。 ### measure的本质 把视图布局使用的“相对值”转化成具体值的过程&#xff0c;即把WRAP_CONTENT,MATCH_PARENT转化为具体的值。 measur…

基于Redis实现分布式锁实战

背景在很多互联网产品应用中&#xff0c;有些场景需要加锁处理&#xff0c;比如&#xff1a;秒杀&#xff0c;全局递增ID&#xff0c;楼层生成等等。大部分的解决方案是基于DB实现的&#xff0c;Redis为单进程单线程模式&#xff0c;采用队列模式将并发访问变成串行访问&#x…

数据分析 绩效_如何在绩效改善中使用数据分析

数据分析 绩效Imagine you need to do a bank transaction, but the website is so slow. The page takes so much time to load, all you can see is a blue circle.想象您需要进行银行交易&#xff0c;但是网站是如此缓慢。 该页面需要花费很多时间来加载&#xff0c;您只能看…

隐私策略_隐私图标

隐私策略During its 2020 Worldwide Developers Conference, Apple spent time on one of today’s hottest topics — privacy. During the past couple of years, Apple has been rolling out various public campaigns aiming to position itself as a company that respect…

您一直在寻找5+个简单的一线工具来提升Python可视化效果

Insightful and aesthetic visualizations don’t have to be a pain to create. This article will prevent 5 simple one-liners you can add to your code to increase its style and informational value.富有洞察力和美学的可视化不必费心创建。 本文将防止您添加到代码中…

figma 安装插件_彩色滤光片Figma插件,用于色盲

figma 安装插件So as a UX Designer, it is important to design with disabilities in mind. One of these is color blindness. It is important to make sure important information on your product is legible to everyone. This is why I like using this tool:因此&…

产品观念:更好的捕鼠器_故事很重要:为什么您需要成为更好的讲故事的人

产品观念&#xff1a;更好的捕鼠器重点 (Top highlight)Telling a compelling story helps you get your point across effectively else you get lost in translation.讲一个引人入胜的故事可以帮助您有效地传达观点&#xff0c;否则您会迷失在翻译中。 Great stories happen…

7月15号day7总结

今天复习了springMVC的框架搭建。 思维导图&#xff1a; 转载于:https://www.cnblogs.com/kangy123/p/9315919.html

设计师的10种范式转变

For $250, a business can pay a graphic designer to create a logo for their business. Or, for $10,000 a business can hire a graphic designer to form a design strategy that contextually places the business’s branding in a stronghold against the market it’s…

面向Tableau开发人员的Python简要介绍(第2部分)

用PYTHON探索数据 (EXPLORING DATA WITH PYTHON) And we’re back! Let’s pick up where we left off in the first article of this series and use the visual we built there as a starting point.我们回来了&#xff01; 让我们从在本系列的第一篇文章中停下来的地方开始&…

设计组合中的10个严重错误可能会导致您丧命

As an agency co-founder and design lead, I’ve been participating in many recruitment processes. I’ve seen hundreds of portfolios and CVs of aspiring designers. If you’re applying for a UI designer position, it is good to have some things in mind and to …

MySQL命令学习

上面两篇博客讲了MySQL的安装、登录&#xff0c;密码重置&#xff0c;为接下来的MySQL命令学习做好了准备&#xff0c;现在开启MySQL命令学习之旅吧。 首先打开CMD&#xff0c;输入命令&#xff1a;mysql -u root -p 登录MySQL。 注意&#xff1a;MySQL命令终止符为分号 (;) …

实验心得_大肠杆菌原核表达实验心得(上篇)

大肠杆菌原核表达实验心得&#xff08;上篇&#xff09;对于大肠杆菌蛋白表达&#xff0c;大部分小伙伴都觉得 so easy! 做大肠杆菌蛋白表达十几年经历的老司机还经常阴沟翻船&#xff0c;被大肠杆菌表达蛋白虐千百遍的惨痛经历&#xff0c;很多小伙伴都有切肤之痛。福因德接下…

自定义版本更新弹窗

目录介绍 1.Animation和Animator区别 2.Animation运行原理和源码分析 2.1 基本属性介绍2.2 如何计算动画数据2.3 什么是动画更新函数2.4 动画数据如何存储2.5 Animation的调用 3.Animator运行原理和源码分析 3.1 属性动画的基本属性3.2 属性动画新的概念3.3 PropertyValuesHold…

《SQL Server 2008从入门到精通》--20180716

1.锁 当多个用户同时对同一个数据进行修改时会产生并发问题&#xff0c;使用事务就可以解决这个问题。但是为了防止其他用户修改另一个还没完成的事务中的数据&#xff0c;就需要在事务中用到锁。 SQL Server 2008提供了多种锁模式&#xff1a;排他锁&#xff0c;共享锁&#x…

googleearthpro打开没有地球_嫦娥五号成功着陆地球!为何嫦娥五号返回时会燃烧,升空却不会?...

目前&#xff0c;嫦娥五号已经带着月壤成功降落到地球上&#xff0c;创造了中国航天的又一里程碑。嫦娥五号这一路走来&#xff0c;困难重重&#xff0c;但都被我国航天科技人员逐一克服&#xff0c;最终圆满地完成了嫦娥五号的月球采样返回地球任务。嫦娥五号最后这一步走得可…

C#中实现对象的深拷贝

深度拷贝指的是将一个引用类型&#xff08;包含该类型里的引用类型&#xff09;拷贝一份(在内存中完完全全是两个对象&#xff0c;没有任何引用关系)..........  直接上代码&#xff1a; 1 /// <summary>2 /// 对象的深度拷贝&#xff08;序列化的方式&#xf…

Okhttp 源码解析

HTTP及okhttp的优势 http结构 请求头 列表内容表明本次请求的客户端本次请求的cookie本次请求希望返回的数据类型本次请求是否采用数据压缩等等一系列设置 请求体 指定本次请求所使用的方法请求所使用的方法 响应头 - 服务器标识 - 状态码 - 内容编码 - cookie 返回给客…

python中定义数据结构_Python中的数据结构。

python中定义数据结构I remembered the day when I made up my mind to learn python then the very first things I learned about data types and data structures. So in this article, I would like to discuss different data structures in python.我记得当初下定决心学习…

builder 模式

首先提出几个问题&#xff1a; 什么是Builder模式&#xff1f;为什么要使用Builder模式&#xff1f;它的优点是什么&#xff0c;那缺点呢&#xff1f;什么情况下使用Builder模式&#xff1f; 关于Builder模式在代码中用的很多&#xff0c;比如AlertDialog, OkHttpClient等。一…