前言:
上一篇文章介绍了企业微信转账,思量了下还是决定把微信支付相关的也介绍下,记录下自己的思路,希望能够帮到初次接触微信支付相关开发的朋友们,对于账号申请这块,本文不做介绍,另外博主主要涉及JAVA开发,因此本文着重介绍服务端的代码部分
步骤:
package com.casom.pay.config;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.core.io.ClassPathResource;
import com.github.wxpay.sdk.IWXPayDomain;
import com.github.wxpay.sdk.WXPayConfig;
/**
*
* @author F
*
*/
public class WeChatPayConfig extends WXPayConfig {
/**
* 微信支付回调地址
*/
public static final String NOTITY_URL = "";
/**
* 证书地址:resource下
*/
public static final String CERT_PATH = "/cert/apiclient_cert.p12";
/**
* pkcs8公钥
*/
public String RSA_PKCS8 = "/rsa/pkcs8.pem";
/**
* 填充算法
*/
public String FILLING_ALGORITHM = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
/**
* API密钥(商户平台-账户设置-API安全-密钥设置)
* 签名使用
*/
private String key = "";
/**
* 不同平台的APPID
*/
public static final class APPID{
/**
* 开放平台APPID
*/
public static final String OPEN_PLATFORM = "";
/**
* 公众平台APPID(公众平台-开发-基本配置)
*/
public static final String PUBLIC_PLATFORM = "";
}
/**
* 默认使用公众平台
*/
private String appid = APPID.PUBLIC_PLATFORM;
/**
* 商户平台账号
*/
private static final String MCHID = "";
/**
* 微信支付,适用场景
*
*/
public static final class TRADE_TYPE{
/**
* 移动APP支付(原生)
*/
public static final String APP = "APP";
/**
* 微信网页支付(只能针对在微信中打开的页面调用支付功能)
*/
public static final String JSAPI = "JSAPI";
/**
* 扫码支付
*/
public static final String NATIVE = "NATIVE";
/**
* H5网页支付,可在其他第三方软件中调用微信支付
*/
public static final String MWEB = "MWEB";
/**
* 付款码支付
*/
public static final String MICROPAY = "MICROPAY";
}
/**
* 无参构造方法
*/
public WeChatPayConfig(){}
/**
* 初始化appid
* @param appid
*/
public WeChatPayConfig(String appid){
this.appid = appid;
}
/**
* 开放平台APPID或者公众平台的APPID
*/
public String getAppID() {
return appid;
}
/**
*
* @param appid
*/
public void setAppID(String appid){
this.appid = appid;
}
/**
* 商户号
*/
public String getMchID() {
return MCHID;
}
/**
* API密钥
*/
public String getKey() {
return key;
}
/**
* API密钥
*/
public void setKey(String key){
this.key = key;
}
/**
* 获取证书
*/
public InputStream getCertStream() {
ClassPathResource cl = new ClassPathResource(CERT_PATH);
try {
return cl.getInputStream();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* 接口请求前缀
*/
@Override
public IWXPayDomain getWXPayDomain() { // 这个方法需要这样实现, 否则无法正常初始化WXPay
IWXPayDomain iwxPayDomain = new IWXPayDomain() {
@Override
public void report(String domain, long elapsedTimeMillis, Exception ex) {
}
@Override
public DomainInfo getDomain(WXPayConfig config) {
return new IWXPayDomain.DomainInfo(doam_api, true);
}
};
return iwxPayDomain;
}
}
package com.casom.pay.service.impl;
import java.math.BigDecimal;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.casom.pay.config.WeChatPayConfig;
import com.casom.pay.service.IWechatPayService;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.github.wxpay.sdk.WxPayBase64;
import com.github.wxpay.sdk.WxpayBank;
import com.github.wxpay.sdk.WxpayRSAEncrypt;
/**
* 业务实现类 - 支付APP/JSAPI/NATIVE - 微信
*/
@Service
public class WechatPayServiceImpl implements IWechatPayService {
private static Logger log = LoggerFactory.getLogger(WechatPayServiceImpl.class);
/**
* JSAPI
*/
@Override
public String unifiedOrder(String body, String outTradeNo, String totalFee, String ip, String openid){
return this.unifiedOrder(new WeChatPayConfig(), WeChatPayConfig.TRADE_TYPE.JSAPI, body, outTradeNo, totalFee, ip, openid);
}
/**
* APP
*/
@Override
public String unifiedOrder(String body, String outTradeNo, String totalFee, String ip){
//移动端必须使用开发平台的应用APPID,不能使用公众平台的APPID
return this.unifiedOrder(new WeChatPayConfig(WeChatPayConfig.APPID.OPEN_PLATFORM), WeChatPayConfig.TRADE_TYPE.APP, body, outTradeNo, totalFee, ip, null);
}
/**
* NATIVE
*/
@Override
public String unifiedOrder_native(String body, String outTradeNo, String totalFee, String ip){
return this.unifiedOrder(new WeChatPayConfig(), WeChatPayConfig.TRADE_TYPE.NATIVE, body, outTradeNo, totalFee, ip, null);
}
/**
* 预支付
* @param trade_type
* @param body
* @param outTradeNo
* @param totalFee
* @param ip
* @param openid
* @return
*/
private String unifiedOrder(WeChatPayConfig config,String trade_type, String body, String outTradeNo, String totalFee, String ip, String openid){
Map rmap = null;
try {
WXPay wxpay = new WXPay(config);
switch (trade_type) {
//移动APP支付
case WeChatPayConfig.TRADE_TYPE.APP:
rmap = this.result_pay_app_json(this.unifiedOrder(config, wxpay, trade_type, body, outTradeNo, totalFee, ip, null), config);
break;
//微信网页支付
case WeChatPayConfig.TRADE_TYPE.JSAPI:
rmap = this.result_pay_jsapi_json(this.unifiedOrder(config, wxpay, trade_type, body, outTradeNo, totalFee, ip, openid), config);
break;
//扫码支付(返回扫码链接,如果是在微信中打开,也可以直接通过跳转的形式调起微信支付)
case WeChatPayConfig.TRADE_TYPE.NATIVE:
rmap = this.unifiedOrder(config, wxpay, trade_type, body, outTradeNo, totalFee, ip, null);
return rmap.get("code_url").toString();
}
} catch (Exception e) {
e.printStackTrace();
}
log.info("resp:{}", JSONObject.toJSONString(rmap));
return JSONObject.toJSONString(rmap);
}
/**
* 预支付
* @param config
* @param wxpay
* @param trade_type
* @param body
* @param outTradeNo
* @param totalFee
* @param ip
* @param openid
* @return
* @throws Exception
*/
private Map unifiedOrder(WeChatPayConfig config,WXPay wxpay,String trade_type,String body, String outTradeNo, String totalFee, String ip, String openid) throws Exception{
Map data = new HashMap();
data.put("appid", config.getAppID());
data.put("mch_id", config.getMchID());
data.put("body", body);
data.put("nonce_str", WXPayUtil.generateNonceStr());
data.put("out_trade_no", outTradeNo);
data.put("total_fee", String.valueOf(new BigDecimal(totalFee).multiply(new BigDecimal(100)).intValue()));
data.put("spbill_create_ip", ip);
data.put("notify_url", WeChatPayConfig.NOTITY_URL);
data.put("trade_type", trade_type);
//JSAPI模式必须传递openid
if(WeChatPayConfig.TRADE_TYPE.JSAPI.equals(trade_type)){
data.put("openid", openid);
}
data.put("sign", WXPayUtil.generateSignature(data, config.getKey()));
//返回预支付结果集
Map rmap = wxpay.unifiedOrder(data);
log.info("unifiedOrder:{}", JSONObject.toJSONString(rmap));
return rmap;
}
/**
* 拼接微信网页端的预支付请求参数
* @param resp
* @param config
* @return
* @throws Exception
*/
private Map result_pay_jsapi_json(Mapresp,WeChatPayConfig config)throws Exception{
//返回给微信网页调起支付
Map rm = new HashMap();
rm.put("appId", resp.get("appid"));
rm.put("timeStamp", String.valueOf(System.currentTimeMillis()/1000));
rm.put("nonceStr", WXPayUtil.generateNonceStr());
rm.put("package", "prepay_id=" + resp.get("prepay_id"));
rm.put("signType", "MD5");
//签名
rm.put("paySign", WXPayUtil.generateSignature(rm, config.getKey()));
return rm;
}
/**
* 拼接APP端的预支付请求参数
* @param resp
* @param config
* @return
* @throws Exception
*/
private Map result_pay_app_json(Mapresp,WeChatPayConfig config) throws Exception{
//返回给APP调起支付
Map rm = new HashMap();
rm.put("appid", resp.get("appid"));
rm.put("partnerid", resp.get("mch_id"));
rm.put("prepayid", resp.get("prepay_id"));
rm.put("noncestr", WXPayUtil.generateNonceStr());
rm.put("timestamp", String.valueOf(System.currentTimeMillis()/1000));
rm.put("package", "Sign=WXPay");
//签名
rm.put("sign", WXPayUtil.generateSignature(rm, config.getKey()));
return rm;
}
}
parameter
参数是服务端返回的,获取方法请查看上文// 页面中引入下列JS代码
var parameter = {
"appId":"wx2421b1c4370ec43b", //公众号名称,由商户传入
"timeStamp":"1395712654", //时间戳,自1970年以来的秒数
"nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串
"package":"prepay_id=u802345jgfjsdfgsdg888",
"signType":"MD5", //微信签名方式:
"paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
}
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest',parameter,
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ){
// 使用以上方式判断前端返回,微信团队郑重提示:
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
}
});
}
if (typeof WeixinJSBridge == "undefined"){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
}
}else{
onBridgeReady();
}
1.后台返回的URL可以直接在前端生成二维码,然后通过微信扫码即可完成支付
2.该URL也可以在微信中直接打开也可调起微信支付
3.如果你是通过第三方分享到微信的网页,不可以通过window.location.href = url或者window.open(url)来调起微信支付,微信网页不会跳转,但可以直接将URL分享到微信中,点击链接打开微信支付