简书原文:超详细微信支付SDK开发并对接沙箱测试
前置配置:
我们先要去接入微信支付,这个网上有很多的教程。注意几个关键的参数即可:
mch_id:商户id,也就是商户号。需要入驻成商户
appid:服务号的appid,需要做关联操作。
证书:主要用于涉及资金回滚接口使用,在下图api安全中设置获得。
apiKey:注意这个不是上面服务号的appSecret,是微信支付商户后台设置的密钥,这个设置后无法再查看,只能重置,请保存好。使用版本是v2就设置v2即可(我这里使用的v2接口),v3看使用情况设置。如下图
一、SDK下载与配置
然后我们需要做的就是复写WXPayConfig这个抽象类,用来配置微信支付的基础信息,如appid,mch_id等,如上图我的实现类为WXPayConfigImpl,具体代码如下:
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
@Descrption :
@Author: zoujie
@Date: 2020-4-15
*/
@Slf4j
public class WXPayConfigImpl extends WXPayConfig{
private StringweChatAppId;
private String mchId;
private String apiKey;
private WXPayConstants.SignTypesignType;
private StringcertPath;
public WXPayConfigImpl(String weChatAppId,String mchId,String apiKey,String certPath,boolean useSandbox) {
this.weChatAppId = weChatAppId;
this.mchId = mchId;
this.apiKey = apiKey;
this.certPath = certPath;
//这里我们提供一个配置类的构造函数,因为在对接微信支付沙箱时,appid和商户id都是正式环境的,只 //有这个apiKey是需要通过接口获取的,下面我通过getSandboxSignKey()方法获取,具体查看下面方法 //代码,详细说明请参考:微信支付沙箱
this.apiKey = useSandbox ? getSandboxSignKey() : apiKey;
this.signType = useSandbox ? WXPayConstants.SignType.MD5 : WXPayConstants.SignType.HMACSHA256;
log.info("微信支付配置已加载:weChatAppId=[{}],mchId=[{}],apiKey=[{}],signType=[{}]",this.weChatAppId,this.mchId,this.apiKey,this.signType);
}
@Override
public StringgetAppID() {
return weChatAppId;
}
@Override
public StringgetMchID() {
return mchId;
}
@Override
public StringgetKey() {
return apiKey;
}
@Override
public InputStreamgetCertStream() {
ClassPathResource resource =new ClassPathResource(certPath);
try {
return resource.getInputStream();
}catch (Exception e) {
log.error(“未成功加载classpath路径下[{}]的证书”,certPath);
}
return null;
}
@Override
public IWXPayDomain getWXPayDomain() {
return new IWXPayDomain() {
@Override
public void report(String domain, long elapsedTimeMillis, Exception ex) {
}
@Override
public DomainInfogetDomain(WXPayConfig config) {
return new DomainInfo(WXPayConstants.DOMAIN_API,true);
}
};
}
/**
* 关闭自动上报
* @return
*/
@Override
public boolean shouldAutoReport() {
return false;
}
public WXPayConstants.SignTypegetSignType(){
return this.signType;
}
//获取沙箱的apiKey
//接口说明:获取接口
private String getSandboxSignKey() {
try {
log.info(“当前配置为使用沙箱对接,准备获取沙箱signKey”);
WXPay wxPay =new WXPay(this,false,true);
Map params =new HashMap();
params.put("mch_id", this.getMchID());
params.put("nonce_str", WXPayUtil.generateNonceStr());
params.put("sign", WXPayUtil.generateSignature(params, this.getKey()));
String strXML = wxPay.requestWithoutCert("/sandboxnew/pay/getsignkey",
params, this.getHttpConnectTimeoutMs(), this.getHttpReadTimeoutMs());
Map result = WXPayUtil.xmlToMap(strXML);
System.out.println("retrieveSandboxSignKey:" + result);
if ("SUCCESS".equals(result.get("return_code"))) {
String sandboxSignkey = result.get(“sandbox_signkey”);
log.info("获取sandbox_signkey=[{}]", sandboxSignkey);
return sandboxSignkey;
}else {
log.info(“获取sandbox_signkey失败:[{}]”,result.get(“return_msg”));
}
return null;
}catch (Exception e) {
log.error(“获取sandbox_signkey异常:[{}]”,e.getLocalizedMessage());
e.printStackTrace();
return null;
}
}
}
其中变量参数均配置在application.properties中,通过@value注解注入,用以在不同环境下注入不同的参数。证书路径就根据自己的证书存放位置配置即可。
二 、开始对接沙箱
微信支付主要是支付下单,也就是微信所描述的统一下单接口,无论哪种支付都是必要的。我们这里以Native支付方式为例子。我们这里使用的是模式二进行开发。时序流程:native(原生)支付模式二时序,详细官方api请参考:微信支付api,我们在工程中使用微信SDK进行请求,它帮我们做了如下的事情:(1)通过配置加入参数appid,mch_id , (2) 自动生成随机字符串 (3) 通过配置的apiKey生成sign签名 (4)需要证书的接口,自动加上我们配置的证书 (5)将返回的xml解析为map
在统一下单接口,我们仅仅需要传递如下参数,参数在文档中有详细的说明,参数传递具体需要参考接口文档,这里仅作最简单的演示。注意:这里的total_fee金额单位为分,类型为int,
调用统一下单
4. 处理返回结果,这里你需要参考文档api和自身的业务逻辑进行相关的处理,我这里不再赘述。
三 、测试沙箱