佰推网logo

400-844-5354

当前位置:网站首页 > 新闻动态 > 小程序制作资讯

开发小程序的支付功能,你了解多少?

日期:2023-08-02访问量:0类型:小程序制作资讯

这次是开发小程序的支付功能。 因为之前没有做过,所以特此记录一下,做个小总结,以备以后使用,也为像我这样的朋友提供参考。 我也一点一点摸索着。 本文仅针对支付流程的开发。 语言以及出现的问题,其他的就略过,只讲解实际的动手开发过程。

名词和实际开发API参见开发文档

而且我用的是普通模式

准备

1.打开微信支付平台成为普通商户,上传商户所需信息(这个不用我多说了)

2、配置小程序并获取appId(小程序项目与支付无关,只需要小程序的appId,其他的就不列出来了)

3、小程序appId与商户支付平台关联,如图:

4、微信支付平台(简称平台)设置密钥,(密钥为签名时要使用的密钥)如图:

然后进入主题。 首先,服务器后端项目需要添加依赖:


	
		com.github.wxpay
		wxpay-sdk
		0.0.3
	

上面的依赖已经官方封装了支付方式和工具,使用起来非常方便,不需要按照API封装从基础一步步实现。 为我们省去了很多麻烦和麻烦。

您也可以从支付平台下载SDK并与demo对比查看具体内容。 内容和依赖关系是相同的。

如图所示:

现在开始看代码。 虽然封装了一些方法,但是项目还是需要配置自己的东西,比如appid、商户号、按键配置等。

package com.xn.weixin.common;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import com.github.wxpay.sdk.WXPayConfig;
//  需要实现一下支付基本的配置,方便调用
	public class MyPayConfig implements WXPayConfig{
			private byte[] certData;
			public void MyConfig() throws Exception {
					//此处暂时用不到,这里是读取证书的地方
			}
		    public String getAppID() {
		        return "这里是你的appid";
		    }
		
		    public String getMchID() {
		    //申请普通商户时分配给你的商户号
		        return "这里是你的商户号";
		    }
		
		    public String getKey() {
		    //这里的key 就是你在支付平台设置的API密钥
		        return "这是就是你的Key了";
		    }
		
		    public InputStream getCertStream() {
		        ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);
		        return certBis;
		    }
		
		    public int getHttpConnectTimeoutMs() {
		        return 8000;
		    }
		
		    public int getHttpReadTimeoutMs() {
		        return 10000;
		    }
}

下一步,我们看一下API文档中的以下几点:

商户系统与微信支付系统主要交互:

1.小程序中调用登录接口获取用户的api,参见公共api【小程序登录API】

2、商户统一调用支付下单。 api请参考公共api【统一订单API】

3.商户调用重签,api参见公共api【重签】

4.商户收到支付通知,api见公共api【支付结果通知API】

5、商户查看支付结果。 若未收到支付通知,商户后台系统可调用【查询订单API】

按照这个顺序,我们的项目就准备好了,也就是第一步已经过去了,现在我们从第二步开始,

开发小程序的支付功能,你了解多少?

小程序登录后=是必须的,所以登录后可以保存获得的,以便以后支付时使用;

注意:

appid必须是最后拉出收银的小程序的appid;

是与appid配对的支付商户账户,收到的资金将进入商户账户;

请填写JSAPI;

是appid对应的用户ID,通过wx.login接口获取

登录后,进入商品页面,选择商品,点击支付。 第一步是下订单或者JSAPI订单。 完成此步骤后,返回获取参数值,用于后续调用支付接口。

让我们看看我们需要使用哪些参数:

下面还有几个参数。 你可以自己看API;

这些类被封装在依赖项中;

微信支付Java SDK

封装了微信支付开发者文档中给出的API。

com..wxpay.sdk.WXPay类提供了相应的方法:

方法名称说明

信用卡付款

统一订单

检查订单

取消订单

关闭订单

要求退款

询问退款事宜

下载声明

交易保护

转换短链接

开发小程序的支付功能,你了解多少?

授权码查询

那么接下来就可以使用上面的配置了

package com.xn.weixin.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayConstants.SignType;
import com.github.wxpay.sdk.WXPayUtil;
import com.xn.system.entity.User;
import com.xn.util.ResultObj;
import com.xn.weixin.common.MyPayConfig;
@RestController
@RequestMapping("/pay/")
public class PaymentController {
@RequestMapping("payment")
public Object getpayment(HttpServletRequest request,String totalfee,String tradeno) throws Exception {
//	获取到当前登录用户,因为这里我保存了openid , 方法大家可以自己处理,这里就不展示了
	User user = User.getCurrentUserInfo().getUser();
	//当前就是我们自己配置的支付配置。appid 商户号 key 什么的;
	MyPayConfig config = new MyPayConfig(); 
	//当前类是官方为我们封装的一些使用的方法
    WXPay wxpay = new WXPay(config);
    //获取到 IP 
    String clientIp = getIpAddress(request);
	System.err.println(clientIp);
	//封装请求参数 参数说明看API文档,当前就不进行讲解了
    Map data = new HashMap();
    data.put("body", "腾讯充值中心-QQ会员充值");
    data.put("out_trade_no", "2016090910595900000012");
    data.put("device_info", "12345679"); //此处设备或商品编号
    data.put("fee_type", "CNY");  // 货币类型  人民币
    
     // 支付中没有小数点,起步以分做为单们,当前为1 分钱,所以自行调整金额 ,这里可以做为传参,
     //选取商品金额传到后端来
     data.put("total_fee", "1"); 
     
    data.put("spbill_create_ip", "123.12.12.123");
    data.put("notify_url", "http://www.example.com/wxpay/notify");
    data.put("trade_type", "JSAPI");  // 此处指定JSAPI
    data.put("product_id", "12");
    data.put("openid", “这是是登录获取到的openId  必传”);
    //调用统一下单方法
    Map order = wxpay.unifiedOrder(data);
    //获取到需要的参数返回小程序
	return order;
	
}
// 获取 IP
public static String getIpAddress(HttpServletRequest request) {
	String ip = request.getHeader("x-forwarded-for");
	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("Proxy-Client-IP");
	}
	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("WL-Proxy-Client-IP");
	}
	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("HTTP_CLIENT_IP");
	}
	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getHeader("HTTP_X_FORWARDED_FOR");
	}
	if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
		ip = request.getRemoteAddr();
	}
	return ip;
}
}

你可能会问为什么这里不包括appid、mchid、key和sign

其实我们上面的依赖已经封装好了,我们会自动获取自己配置的appid mchid和key,放入集合中然后进行签名加密。 我们看一下依赖中的方法:

我们找到这个方法来看看具体内容:

/**
     * 作用:统一下单
* 场景:公共号支付、扫码支付、APP支付 * @param reqData 向wxpay post的请求数据 * @return API返回数据 * @throws Exception */ public Map unifiedOrder(Map reqData) throws Exception { return this.unifiedOrder(reqData, config.getHttpConnectTimeoutMs(), this.config.getHttpReadTimeoutMs()); } /** * 作用:统一下单
* 场景:公共号支付、扫码支付、APP支付 * @param reqData 向wxpay post的请求数据 * @param connectTimeoutMs 连接超时时间,单位是毫秒 * @param readTimeoutMs 读超时时间,单位是毫秒 * @return API返回数据 * @throws Exception */ public Map unifiedOrder(Map reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception { String url; if (this.useSandbox) { url = WXPayConstants.SANDBOX_UNIFIEDORDER_URL_SUFFIX; } else { url = WXPayConstants.UNIFIEDORDER_URL_SUFFIX; } if(this.notifyUrl != null) { reqData.put("notify_url", this.notifyUrl); } String respXml = this.requestWithoutCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs); return this.processResponseXml(respXml); }

上面最后第二行使用了this.()方法,其作用是

添加appid,,,,标志到地图,

它会自动发送请求进行我们的加密签名、xml转换图等操作,我们只需接收返回的数据并再次调用小程序支付接口即可

	 /**
 * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign 
* 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口 * * @param reqData * @return * @throws Exception */ public Map fillRequestData(Map reqData) throws Exception { reqData.put("appid", config.getAppID()); reqData.put("mch_id", config.getMchID()); reqData.put("nonce_str", WXPayUtil.generateNonceStr()); if (SignType.MD5.equals(this.signType)) { reqData.put("sign_type", WXPayConstants.MD5); } else if (SignType.HMACSHA256.equals(this.signType)) { reqData.put("sign_type", WXPayConstants.HMACSHA256); } reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType)); return reqData; }

当我们的小程序收到服务器返回的参数数据后,我们就可以再次调用wx.()来发起微信支付。

统一订单返回的参数:

var data = {
		变量:金额什么的参数
}
	//小程序封装的post请求 
	action.post("请求url",“data参数”,function( res){
	//支付请求 但是此处有大坑,一定要注意,
	
	wx.requestPayment(
		{
		"timeStamp":"",
		"nonceStr": "",
		"package": "",
		"signType": "MD5",
		"paySign": "",
		"success":function(res){},
		"fail":function(res){},
		"complete":function(res){}
	})
	})

不过这里有一个大坑,要小心。

//api说只有五个参数。 其实有一个appid需要添加。 api中也提到了,但是发起支付的api示例中没有。 如果不注意很容易被忽视。 问题,这个需要自己测试,我就不多演示了

至此,基本上就结束了,但是当我第一次发起这一步的时候,支付签名的验证总是失败。 我给大家讲一下改动的内容,原理需要同志们研究一下,

下面介绍几个小方法,调用起来比较方便:

	// 时间戳
timeStamp:function () {
  return parseInt(new Date().getTime() / 1000) + ''
},
/* 随机数 */
randomString:function () {
  var chars = 'A2345678';    
  var maxPos = chars.length;
  var pwd = '';
  for (var i = 0; i < 32; i++) {
    pwd += chars.charAt(Math.floor(Math.random() * maxPos));
  }
  return pwd;
},
  // 调起支付签名    这里我不太明白,虽然前面加载签名和后面验证,但里面加了随机数为什么验证还能通过我没还转过	      弯来,希望大家能搞明白吧,到时候可不要吝啬留言讲解一下下
MixedencryMD5:function (data,randomString,timeStamp) {
  var pay =  "appId=" + config.appid + "&nonceStr=" + randomString + "&package=prepay_id=" + data.prepay_id + 		  "&signType=MD5" + "&timeStamp=" + timeStamp+ "&key=" + config.key;  
  console.log(md5.hexMD5(pay))
  return  md5.hexMD5(pay);
},

完成通话小程序支付:

changePayment:function(){
  var that = this;
  var fee = that.data.inputValue*100;
  //小程序封装的post请求 
	action.post("请求url",“data参数”,function( res){
	//支付请求 但是此处有大坑,一定要注意,
	
    //随机数  
    var randomString = that.randomString();
    //当前时间
    var time = that.timeStamp();
    //签名
    var parSigns = that.MixedencryMD5(res.data,randomString,time);
      wx.requestPayment({ 
        appId:config.appid,
        timeStamp: time,
        nonceStr: randomString,
        package: "prepay_id="+res.data.prepay_id,
        signType: "MD5",
        paySign: parSigns,
        success (ress) {
          console.log(ress)
        },
        fail (ress) {
          console.log(ress)
        }
      })
    
  })

至此,我已经完成了小程序支付,并且支付成功,很开心。

接下来我再把效果图放上来,然后这篇文章就结束了,请大家多多指教,有问题评论区见


TAG标签:微信小程序 

声明:本文来自投稿,不代表佰推网立场,如若转载,请注明出处:http://www.ccsuit.cn/news/show351.html 若本站的内容无意侵犯了贵司版权,请给我们来信,我们会及时处理和回复。

相关新闻

相关案例

X微信咨询

截屏,微信识别二维码

微信号:dianzana1989

(点击微信号复制,添加好友)

  打开微信

微信号已复制,请打开微信添加咨询详情!