微信支付SDK3.0.9(1.移动端APP支付,2.微信网页调起支付JSAPI,3.微信扫码支付)

前言:
上一篇文章介绍了企业微信转账,思量了下还是决定把微信支付相关的也介绍下,记录下自己的思路,希望能够帮到初次接触微信支付相关开发的朋友们,对于账号申请这块,本文不做介绍,另外博主主要涉及JAVA开发,因此本文着重介绍服务端的代码部分

步骤:

  • 下载微信官网的SDK(需要适当的改造服务端代码,上篇文章已经有说明)
  • 服务端生成APP端调用微信支付的JSON字符串(APP请求微信支付的所需参数)
  • 原生安卓(IOS)通过服务端传递的JSON字符串发起微信支付
  • 回调(需要微信商户平台设置回调接口授权,本文不介绍)
  • 参数说明(trade_type=APP的必须传递开放平台的APPID并不是公众平台的APPID)
  • 微信官网开发文档

第一步:前往微信官网下载SDK3.0.9(源码下载)

  • APP前端(IOS/Android)微信官网下载地址
  • 服务端(JAVA/PHP/.NET)微信官网下载地址

第二步:后端生成预支付JSON串(APP/JSAPI/NATIVE)

  • 在自己的工程中创建一个继承WxPayConfig的类(前往上一篇文章)
  • WeChatPayConfig.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;
	}
}

  • 创建Controller或者Service(WechatPayServiceImpl.java)
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;
	}
}

第三步,前端调起微信支付

  • IOS,安卓开发
  • JSAPI前端开发(注:只能在微信中打开网页,才能调起支付)
  • 注:代码中的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();
}
  • NATIVE(微信扫码支付)

1.后台返回的URL可以直接在前端生成二维码,然后通过微信扫码即可完成支付
2.该URL也可以在微信中直接打开也可调起微信支付
3.如果你是通过第三方分享到微信的网页,不可以通过window.location.href = url或者window.open(url)来调起微信支付,微信网页不会跳转,但可以直接将URL分享到微信中,点击链接打开微信支付

介绍就到这里,希望能帮到朋友们,需要源码的朋友,请点击我(注:不包含前端代码)

你可能感兴趣的:(微信开发,JAVA,微信支付,JSAPI,APP,NATIVE)