微信公众号开发《五》基于Java实现微信支付(公众号支付)简单教程

最近公司需求,需要在微信公众号内完成支付,找到官方文档,文档还可以,讲的也挺详细,不过有一个地方很坑爹,就是微信内H5调起支付需要一个签名,而他给出的参考签名方式跟统一下单签名一致,害的我以为,他这个签名就是统一下单那个签名,后面找了很久看了好多博客才明白这个签名是怎么生成的(JS-SDK中微信支付有说明)。弄了半天,汗颜。下面进入正题。

微信支付分为很多种,有刷卡支付,公众号支付,扫码支付,APP支付,H5支付,小程序支付,本教程只讲解公众号支付。主要分三大块来讲解。

1.公众号支付介绍
微信支付只面向已认证客户,需要申请,申请成功后有个商家号,还要一个API密匙即key(微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->密钥设置)。而公众号支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。应用场景有:
◆ 用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付
◆ 用户的好友在朋友圈、聊天窗口等分享商家页面连接,用户点击链接打开商家页面,完成支付
◆ 将商户页面转换成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付

2.开发流程

在这里贴出官方文档地址https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1。有兴趣的可以研究研究,贴出最主要的业务流程图:
啥,看不下去,那简单来说,你要掌握三点:

1.在商家后台设置支付目录, 设置路径:商户平台-->产品中心-->开发配置。填写你项目所在域名

2.在公众号后台 设置授权域名,因为在统一下单接口中要求必传用户openid,而获取openid则需要您在公众平台设置获取openid的域名,只有被设置过的域名才是一个有效的获取openid的域名,否则将获取失败。

3.调通统一下单 支付结果通知接口(详细看demo)

tip:如果不知道如何获取openid,可以看本人另外一篇博客微信公众号开发《一》OAuth2.0网页授权认证获取用户的详细信息,实现自动登陆

3.demo展示
demo使用了包:xstream-1.3.1.jar,jdom.jar,用于把数据封装成xml格式与xml解析。首先我们把请求参数封装成类
/**
 * 统一下单请求参数
 * @author lhao
 *
 */
public class UnifiedOrderRequest {
	//变量名	字段名	必填	 	类型		示例值	描述
	private String appid;//	公众账号ID   是		String(32)	wxd678efh567hg6787	微信支付分配的公众账号ID(企业号corpid即为此appId)
	private String mch_id;//商户号  必填	String(32)	1230000109	微信支付分配的商户号
	private String device_info;	//设备号	否		String(32)	013467007045764	自定义参数,可以为终端设备号(门店号或收银设备ID),PC网页或公众号内支付可以传"WEB"
	private String nonce_str;//随机字符串	是 	     String(32)	5K8264ILTKCH16CQ2502SI8ZNMTM67VS	随机字符串,长度要求在32位以内。推荐随机数生成算法
	private String sign;//签名	是 	     String(32)	  C380BEC2BFD727A4B6845133519F3AD6	通过签名算法计算得出的签名值,详见签名生成算法
	private String sign_type;//签名类型	sign_type	否	String(32)	HMAC-SHA256	签名类型,默认为MD5,支持HMAC-SHA256和MD5。
	private String body;//商品描述	body 是	 String(128)	腾讯充值中心-QQ会员充值  商品简单描述,该字段请按照规范传递,具体请见参数规定	
	private String detail;//商品详情	detail	否	String(6000)	 	单品优惠字段(暂未上线)
	private String attach;//附加数据	attach	否	String(127)	深圳分店	附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。
	private String out_trade_no;//商户订单号	out_trade_no	是	String(32)	20150806125346	商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*@ ,且在同一个商户号下唯一。详见商户订单号
	private String fee_type;//标价币种	fee_type	否	String(16)	CNY	符合ISO 4217标准的三位字母代码,默认人民币:CNY,详细列表请参见货币类型
	private String total_fee;//标价金额	total_fee	是	Int	88	订单总金额,单位为分,详见支付金额
	private String spbill_create_ip;//终端IP	spbill_create_ip	是	String(16)	123.12.12.123	APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。
	private String time_start;//交易起始时间	time_start	否	String(14)	20091225091010	订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
	private String time_expire;//交易结束时间	time_expire	否	String(14)	20091227091010	订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则   注意:最短失效时间间隔必须大于5分钟
	private String goods_tag;//订单优惠标记	goods_tag	否	String(32)	WXG	订单优惠标记,使用代金券或立减优惠功能时需要的参数,说明详见代金券或立减优惠
	private String notify_url;//通知地址	notify_url	是	String(256)	http://www.weixin.qq.com/wxpay/pay.php	异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。
	private String trade_type;//交易类型	trade_type	是	String(16)	JSAPI	取值如下:JSAPI,NATIVE,APP等,说明详见参数规定
	private String product_id;//商品ID	product_id	否	String(32)	12235413214070356458058	trade_type=NATIVE时(即扫码支付),此参数必传。此参数为二维码中包含的商品ID,商户自行定义。
	private String limit_pay;//指定支付方式	limit_pay	否	String(32)	no_credit	上传此参数no_credit--可限制用户不能使用信用卡支付
	private String openid;//用户标识	openid	否	String(128)	oUpF8uMuAJO_M2pxb1Q9zNjWeS6o	trade_type=JSAPI时(即公众号支付),此参数必传,此参数为微信用户在商户对应appid下的唯一标识。openid如何获取,可参考【获取openid】。企业号请使用【企业号OAuth2.0接口】获取企业号内成员userid,再调用【企业号userid转openid接口】进行转换
	
	//省略get,set方法
}
/**
 * 统一下单返回参数
 * @author lhao
 *
 */
public class UnifiedOrderRespose {
    private String return_code;             //返回状态码
    private String return_msg;              //返回信息
    private String appid;                   //公众账号ID
    private String mch_id;                  //商户号
    private String device_info;             //设备号
    private String nonce_str;               //随机字符串
    private String sign;                    //签名
    private String result_code;             //业务结果
    private String err_code;                //错误代码
    private String err_code_des;            //错误代码描述
    private String trade_type;              //交易类型
    private String prepay_id;               //预支付交易会话标识
    private String code_url;                //二维码链接
    
    //省略get/set方法
}
/**
 * 常量
 */
public class WXPayConstants {

    public enum SignType {
        MD5, HMACSHA256
    }
    public static final String FAIL     = "FAIL";
    public static final String SUCCESS  = "SUCCESS";
    public static final String HMACSHA256 = "HMAC-SHA256";
    public static final String MD5 = "MD5";
    public static final String FIELD_SIGN = "sign";
    public static final String FIELD_SIGN_TYPE = "sign_type";

}
MD5加密工具类,封装参数、请求工具类
import java.security.MessageDigest;
/**
 * MD5工具类
 * @author lh
 */
public class MD5Util {
    public final static String MD5(String s) {
        char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};       

        try {
            byte[] btInput = s.getBytes();
            // 鑾峰緱MD5鎽樿绠楁硶鐨�MessageDigest 瀵硅�?
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 浣跨敤鎸囧畾鐨勫瓧鑺傛洿鏂版憳瑕�?
            mdInst.update(btInput);
            // 鑾峰緱�?�嗘�?
            byte[] md = mdInst.digest();
            // 鎶婂瘑鏂囪浆鎹㈡垚鍗佸叚杩涘埗鐨勫瓧绗︿覆褰㈠紡
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            String md5Str = new String(str); 
            return md5Str;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.security.MessageDigest;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import wp.WXPayConstants.SignType;
import javax.crypto.Mac;
import javax.crypto.spec.Se
  • 10
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 31
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 31
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值