开发准备
参考文档 JSAPI支付开发文档
支付方式
目前微信主流的支付方式有以下6种
方式 | 说明 |
---|---|
付款码支付 | 付款码支付是用户展示微信钱包内的“刷卡条码/二维码”给商户系统扫描后直接完成支付的模式。主要应用线下面对面收银的场景。 |
Native支付 | Native支付是商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。该模式适用于PC网站支付、实体店单品或订单支付、媒体广告支付等场景。 |
JSAPI支付 | JSAPI支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。 |
APP支付 | APP支付又称移动端支付,是商户通过在移动端应用APP中集成开放SDK调起微信支付模块完成支付的模式。 |
H5支付 | H5支付主要是在手机、ipad等移动设备中通过浏览器来唤起微信支付的支付产品。 |
小程序支付 | 小程序支付是专门被定义使用在小程序中的支付产品。目前在小程序中能且只能使用小程序支付的方式来唤起微信支付。 |
因为前面做过关于公众号的文章,因此这里主要介绍JSAPI支付,后面的开发等也围绕于此。
JSAPI应用场景有:
- 用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付
- 用户的好友在朋友圈、聊天窗口等分享商家页面连接,用户点击链接打开商家页面,完成支付
- 将商户页面转换成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付
核心名词
不同于微信公众号的测试开发,可以使用内网穿透,和普通的测试账号等。微信支付要求开发者,必须要有一个已通过验证的真实商户号,且该商户号开通支付功能,以及该商户下有真实的公众号等。
-
【微信商户平台】
微信商户平台是微信支付相关的商户功能集合,包括参数配置、支付数据查询与统计、在线退款、代金券或立减优惠运营等功能
平台入口:http://pay.weixin.qq.com。 -
【微信公众平台】
微信公众平台是微信公众账号申请入口和管理后台。商户可以在公众平台提交基本资料、业务资料、财务资料申请开通微信支付功能。
平台入口:http://mp.weixin.qq.com。 -
【微信支付系统】
微信支付系统是指完成微信支付流程中涉及的API接口、后台业务处理系统、账务系统、回调通知等系统的总称。 -
【商户证书】
商户证书是微信提供的二进制文件,商户系统发起与微信支付后台服务器通信请求的时候,作为微信支付后台识别商户真实身份的凭据。 -
【商户后台系统】
商户后台系统是商户后台处理业务系统的总称,例如:商户网站、收银系统、进销存系统、发货系统、客服系统等,一般关联开发者自己的数据库。 -
【签名】
商户后台和微信支付后台根据相同的密钥和算法生成一个结果,用于校验双方身份合法性。签名的算法由微信支付制定并公开,常用的签名方式有:MD5、SHA1、SHA256、HMAC等。 -
【支付密码】
支付密码是用户开通微信支付时单独设置的密码,用于确认支付完成交易授权。该密码与微信登录密码不同。 -
【Openid】
用户在公众号内的身份标识,不同公众号拥有不同的openid。商户后台系统通过登录授权、支付通知、查询订单等API可获取到用户的openid。主要用途是判断同一个用户,对用户发送客服消息、模版消息等。
申请的核心账户参数:
账户参数说明
邮件中参数 | API参数名 | 详细说明 |
---|---|---|
APPID | appid | appid是微信公众账号或开放平台APP的唯一标识,在公众平台申请公众账号或者在开放平台申请APP账号后,微信会自动分配对应的appid,用于标识该应用。可在微信公众平台–>开发–>基本配置里面查看,商户的微信支付审核通过邮件中也会包含该字段值。 |
微信支付商户号 | mch_id | 商户申请微信支付后,由微信支付分配的商户收款账号。 |
API密钥 | key | 交易过程生成签名的密钥,仅保留在商户系统和微信支付后台,不会在网络中传播。商户妥善保管该Key,切勿在网络中传输,不能在其他客户端中存储,保证key不会被泄漏。商户可根据邮件提示登录微信商户平台进行设置。也可按以下路径设置:微信商户平台(pay.weixin.qq.com)–>账户中心–>账户设置–>API安全–>密钥设置 |
Appsecret | secret | AppSecret是APPID对应的接口密码,用于获取接口调用凭证access_token时使用。在微信支付中,先通过OAuth2.0接口获取用户openid,此openid用于微信内网页支付模式下单接口使用。可登录公众平台–>微信支付,获取AppSecret(需成为开发者且帐号没有异常状态)。 |
协议规则
商户接入微信支付,调用API必须遵循以下规则:
传输方式 | 为保证交易安全性,采用HTTPS传输 |
---|---|
提交方式 | 采用POST方法提交 |
数据格式 | 提交和返回数据都为XML格式,根节点名为xml |
字符编码 | 统一采用UTF-8字符编码 |
签名算法 | MD5/HMAC-SHA256 |
签名要求 | 请求和接收数据均需要校验签名,详细方法请参考安全规范-签名算法 |
证书要求 | 调用申请退款、撤销订单、红包接口等需要商户api证书,各api接口文档均有说明。 |
判断逻辑 | 先判断协议字段返回,再判断业务返回,最后判断交易状态 |
开发中代码配置的参数(实际开发中建议直接在属性文件中配置,便于环境切换)
// 公众号、小程序appid
public static String APP_ID = "xxxxxxxxx";
// AppSecret
public static String SECRET = "xxxxxxxxx";
// 商户号
public static final String MCH_ID = "xxxxxxxxx";
// API密钥
public static final String API_KEY = "xxxxxxxxx";
// 网页授权域名,JSAPI支付授权目录,JS接口安全域名
public static final String AUTH_URL = "xxxxxxxxx";
以上参数不便公开。如果公司有现成的支付账户最好,没有的话恐怕只能在某宝租用一下了,但没有这些不影响前期的业务开发。
业务梳理
业务流程时序图
对于开发者来说,发起支付的过程中,
后端:主要调用了JSAPI支付中的三个接口:【统一下单API】、【支付结果通知API】、【查询订单API】
前端:
前端微信内H5调起支付,提供用户触发微信支付的button和JSON数据传输。
开始开发
项目搭建
一、采用SpringBoot+Thymeleaf结构,参考微信公众号快速开发(二)项目搭建与被动回复
二、引入官方SDK工具包
阅读文档后发现,对于xml解析,加密算法等其实都时常用的方法,微信为我们直接提供了常用工具类方法的半成品,注意,这些只能是半成品,使用时需要做适当的更改。
链接:SDK与DEMO下载,选择JAVA版本下载后解压即可
代码开发
公众号配置
一、将公众号和商户的信息注入到Bean中
@Component
public class WXPayConfigExtend extends WXPayConfig {
private byte[] certData;
private WXPayConfigExtend() throws Exception {
// String certPath = WXPayConstants.APICLIENT_CERT;
// File file = new File(certPath);
// InputStream certStream = new FileInputStream(file);
// this.certData = new byte[(int) file.length()];
// certStream.read(this.certData);
// certStream.close();
}
@Override
public String getAppID() {
return WXPayConstants.APP_ID;
}
@Override
public String getMchID() {
return WXPayConstants.MCH_ID;
}
@Override
public String getKey() {
return WXPayConstants.API_KEY;
}
@Override
public InputStream getCertStream() {
ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
return certBis;
}
@Override
public int getHttpConnectTimeoutMs() {
return 2000;
}
@Override
public int getHttpReadTimeoutMs() {
return 10000;
}
@Override
public IWXPayDomain getWXPayDomain() {
return WXPayDomainSimpleImpl.instance();
}
public String getPrimaryDomain() {
return "api.mch.weixin.qq.com";
}
public String getAlternateDomain() {
return "api2.mch.weixin.qq.com";
}
@Override
public int getReportWorkerNum() {
return 1;
}
@Override
public int getReportBatchSize() {
return 2;
}
}
获取openid
需页面提供网页授权,以获取openid,关于微信网页授权可参考:微信公众号快速开发(四)微信网页授权
页面:
页面这里直接设计了一个可以发起预支付的按钮的静态页面:templates/preOrder.html
里面包含了跳转到后端支付接口的表单:
<form name=wexinpayment action='http://chety.mynatapp.cc/api/v1/wechat1/placeOrder' method=post target="_blank">
...
Thymeleaf下页面转发的控制器:
@Controller
@RequestMapping("/api/v1/wechat1")
pub