iOS开发总结--三方平台开发之微信支付
1.前言
现在很多应用都有支付功能,支付也是开发中比较麻烦的一个部分。其实,最麻烦的部分是商户帐号的审核,如果没有商户帐号,就没有你要给钱的那个对公账户。
2.关于交易
在这个金融类项目的开发中,接触了一些金融常识。比如,要是需要进行融资的话,必须要有对公账户,若没有对公账户,那么进行的融资交易即视为非法集资。而申请微信或支付宝的商家账户其实就是开通一个对公账户。但是,最烦人的就是申请账户,等待审核。
3.微信支付
I)业务流程
以上的图是微信官方的图,其实挺坑人的,时序图弄的那么麻烦。
其实简言之就两步:
1)下预支付订单,调用https://api.mch.weixin.qq.com/pay/unifiedorder 统一支付API
2)调起微信支付接口
II)接入微信SDK
微信的支付和微信分享是相同的SDK,再上一篇中已经把SDK引入到项目中不需要再引入了。新的SDK版本为1.6.2,去掉了之前版本预支付调用统一下单API的方法,当然,统一下单接口本来就应该后台调用,以便后台存储商户订单和微信后台的预支付订单。后台调用统一下单接口后,将后台存储的订单ID和预支付ID(prepayid)返回给iOS/Android移动端即可,以便移动端调起微信并让用户支付订单金额。
虽然,新版SDK去掉了预支付流程,但是为了
4.支付单例的设计
支付单例类似于分享单例。为什么要拆开到单独的类中?因为,单独拿出来以便今后再集成支付宝的支付。
I)头文件
//
// NYPaymentManager.h
// NYShare
//
// Created by 倪瑶 on 15/12/10.
// Copyright © 2015年 nycode. All rights reserved.
// #import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "NYXMLParser.h"
#import "NYWXPayUtility.h"
#import "WXApi.h"
//暂时用 创友
#define WX_PAY_APP_ID @"" /**< 微信开放应用APP ID !重要:必须是和商户关联的APP ID */
#define WX_PAY_APP_SECRET @"" /**< 微信开放应用APP SECRET */ #define WX_PAY_API_KEY @"" /**< API密钥*/
#define WX_PAY_PARTNER_ID @"" /**< 微信支付商户号 */
#define WX_PAY_DEVICE_INFO @"" /**< 支付设备号或门店号 */
#define WX_PAY_BILL_CREATE_IP @"192.168.0.1" /**< 发器支付的机器ip */
#define WX_PAY_NOTIFY_URL @"" /**< 回调URL,接收异步通知 */
#define WX_PAY_UNIFIEDORDER_API @"https://api.mch.weixin.qq.com/pay/unifiedorder" /**< 统一订单接口,详见https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=9_1 */
#define WX_PAY_PACKAGE @"Sign=WXPay" #define PAYMENT_ERROR_DOMAIN_WX_PREPAYID @"PAYMENT_ERROR_DOMAIN_WX_PREPAYID" //获取prepayid失败
#define PAYMENT_ERROR_DOMAIN_WX_SIGN @"PAYMENT_ERROR_DOMAIN_WX_SIGN" //服务器返回签名验证错误
#define PAYMENT_ERROR_DOMAIN_WX_SERVER @"PAYMENT_ERROR_DOMAIN_WX_SERVER" //请求接口返回错误
#define PAYMENT_ERROR_DOMAIN_WX_PRICE @"PAYMENT_ERROR_DOMAIN_WX_PRICE" //价格为负数
#define PAYMENT_ERROR_DOMAIN_WX_RESPONSE @"PAYMENT_ERROR_DOMAIN_WX_RESPONSE" //服务器返回对象为空
#define PAYMENT_ERROR_DOMAIN_WX_REQUEST @"PAYMENT_ERROR_DOMAIN_WX_REQUEST" //支付请求失败
#define PAYMENT_ERROR_DOMAIN_WX_RESULT_FAIL @"PAYMENT_ERROR_DOMAIN_WX_RESULT_FAIL"//返回失败
#define PAYMENT_ERROR_DOMAIN_WX_PAYFAILED @"PAYMENT_ERROR_DOMAIN_WX_PAYFAILED"//可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等
#define PAYMENT_ERROR_DOMAIN_WX_PAYCANCELED @"PAYMENT_ERROR_DOMAIN_WX_PAYCANCELED"
/**
* 支付错误码类型
**/
typedef NS_ENUM(NSInteger, NYPaymentErrorCode) {
NYPaymentErrorCodeWeChatSignVerifyError,
NYPaymentErrorCodeWeChatApiResponseError,
NYPaymentErrorCodeWeChatGetPrePayIDFailed,
NYPaymentErrorCodeWeChatPriceLow,
NYPaymentErrorCodeWeChatResponseError,
NYPaymentErrorCodeWeChatRequestError,
NYPaymentErrorCodeWeChatResultCodeFail,
NYPaymentErrorCodeWeChatPayFailed,
NYPaymentErrorCodeWeChatPayCanceled,
NYPaymentErrorCodeWeChatPaySuccess,//暂不用,最好后台请求获取,以服务器饭或为准
NYPaymentErrorCodeALiPay,
}; /**
* 支付类型
**/
typedef NS_ENUM(NSInteger, NYPaymentType) {
NYPaymentTypeWeChat,
NYPaymentTypeALiPay,
}; /**
* 回调
* @param error 支付请求返回的错误
* @param requestObject 支付请求发送的对象
* @param responseObject 支付相应返回的对象
**/
typedef void(^NYPaymentComletion)(NSError *error, id requestObject, id responseObject); /**
* 支付订单对象
**/
@interface NYPaymentObject : NSObject
@property (strong, nonatomic) NSString *orderID; /**< 商户订单ID,商户后台提供 */
@property (strong, nonatomic) NSString *orderTitle; /**< 商户订单标题,商户后台提供 */
@property (strong, nonatomic) NSString *orderPrice; /**< 订单价格,单位为元 */
@property (strong, nonatomic) NSString *wxPrePayID; /**< 微信预支付订单号,微信支付时必填! */
@end
/**
* 支付通用类
**/
@interface NYPaymentManager : NSObject <WXApiDelegate>
@property (strong, nonatomic) NYPaymentComletion completion; /**< 回调 */ /**
* 单例
**/
+ (instancetype)defaultManager;
- (void)registerPaymentApp;
/**
* 微信移动端独立发送统一订单请求方法
* @param orderID 商户订单ID,商户后台提供
* @param orderTitle 商户订单标题,商户后台提供
* @param price 订单价格,单位为分
* @param completion 业务回调
* @brief 该方法用于没有后台请求统一下单接口的情况
* @description 仅供测试用
**/
//- (void)sendWeChatPrePayRequestWithOrderID:(NSString *)orderID orderTitle:(NSString *)orderTitle price:(NSString *)price completion:(NYPaymentComletion)completion;
/**
* 微信支付方法
* @param object 支付的订单对象
* @param completion 支付的回调方法
**/
- (void)payForWeChatWithOrderObject:(NYPaymentObject *)object completion:(NYPaymentComletion)completion;
/**
* 支付统一方法
* @param payType 支付类型,阿里支付、微信支付
* @param object 支付订单对象
* @param completion 回调函数
**/
- (void)payForType:(NYPaymentType)payType paymentObject:(NYPaymentObject *)object completion:(NYPaymentComletion)completion;
/**
* 分享打开三方应用代理回调方法
**/
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url;
/**
* 分享打开三方应用代理回调方法
**/
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
@end
II)实现文件
//
// NYPaymentManager.m
// NYShare
//
// Created by 倪瑶 on 15/12/10.
// Copyright © 2015年 nycode. All rights reserved.
// #import "NYPaymentManager.h" @implementation NYPaymentObject @end @implementation NYPaymentManager + (instancetype)defaultManager {
static NYPaymentManager *manager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
manager = [[self alloc] init];
});
return manager;
} - (instancetype)init {
self = [super init];
if (self) { }
return self;
} - (void)registerPaymentApp {
[WXApi registerApp:WX_PAY_APP_ID]; } #pragma mark - payment
- (void)payForType:(NYPaymentType)payType paymentObject:(NYPaymentObject *)object completion:(NYPaymentComletion)completion {
switch (payType) {
case NYPaymentTypeALiPay: { break;
}
case NYPaymentTypeWeChat: {
[[NYPaymentManager defaultManager] payForWeChatWithOrderObject:object completion:completion];
break;
}
default:
break;
}
} - (void)payTestForWeChatWithOrderObject:(NYPaymentObject *)object completion:(NYPaymentComletion)completion {
NSString *centPrice = [NSString stringWithFormat:@"%.f",object.orderPrice.floatValue*]; [self sendWeChatPrePayRequestWithOrderID:object.orderID orderTitle:object.orderTitle price:centPrice completion:^(NSError *error, id requestObject, id responseObject) {
if (error != nil) {
// NSLog(@"Domain:%@\n Description:%@\n request:%@\n", error.domain, error.description, requestObject);
if (completion != nil) {
completion(error, requestObject, nil);
}
} else { if (centPrice.floatValue < ) {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_PRICE code:NYPaymentErrorCodeWeChatPriceLow userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"价格为负数!"]}];
if (completion != nil) {
completion(error, nil, nil);
}
} else {
if (responseObject != nil) {
NSString *time_stamp, *nonce_str;
//设置支付参数
time_t now;
time(&now);
time_stamp = [NSString stringWithFormat:@"%ld", now];
nonce_str = [NYWXPayUtility md5:time_stamp];
//支付请求的参数一定要核对清楚
PayReq *payRequest = [[PayReq alloc] init];
payRequest.openID = WX_PAY_APP_ID;
payRequest.partnerId = WX_PAY_PARTNER_ID;
payRequest.prepayId = [responseObject objectForKey:@"prepayid"];//!!!!
payRequest.nonceStr = nonce_str;
payRequest.timeStamp = time_stamp.intValue;
payRequest.package = WX_PAY_PACKAGE;//???? //第二次签名参数列表
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: WX_PAY_APP_ID forKey:@"appid"];
[signParams setObject: nonce_str forKey:@"noncestr"];
[signParams setObject: WX_PAY_PACKAGE forKey:@"package"];
[signParams setObject: WX_PAY_PARTNER_ID forKey:@"partnerid"];
[signParams setObject: time_stamp forKey:@"timestamp"];
[signParams setObject: [responseObject objectForKey:@"prepayid"] forKey:@"prepayid"];
//[signParams setObject: @"MD5" forKey:@"signType"];
//生成签名
NSString *sign = [self createMd5Sign:signParams];
payRequest.sign = sign;//????
BOOL status = [WXApi sendReq:payRequest];
if (!status) {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_REQUEST code:NYPaymentErrorCodeWeChatRequestError userInfo:@{NSLocalizedDescriptionKey:@"支付请求失败!"}];
if (completion != nil) {
completion(error, nil, nil);
}
} else {
if (completion != nil) {
completion(nil, nil, nil);
}
} } else {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_RESPONSE code:NYPaymentErrorCodeWeChatResponseError userInfo:@{NSLocalizedDescriptionKey:@"服务器返回对象为空!"}];
if (completion != nil) {
completion(error, nil, nil);
}
}
} }
}];
} - (void)payForWeChatWithOrderObject:(NYPaymentObject *)object completion:(NYPaymentComletion)completion {
if (object.wxPrePayID.length == ) {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_PREPAYID code:NYPaymentErrorCodeWeChatGetPrePayIDFailed userInfo:@{NSLocalizedDescriptionKey:@"获取prepayid失败!\n"}];
if (completion != nil) {
completion(error, nil, nil);
}
} else {
NSString *time_stamp, *nonce_str;
//设置支付参数
time_t now;
time(&now);
time_stamp = [NSString stringWithFormat:@"%ld", now];
nonce_str = [NYWXPayUtility md5:time_stamp];
//支付请求的参数一定要核对清楚
PayReq *payRequest = [[PayReq alloc] init];
payRequest.openID = WX_PAY_APP_ID;
payRequest.partnerId = WX_PAY_PARTNER_ID;
payRequest.prepayId = object.wxPrePayID;//!!!!
payRequest.nonceStr = nonce_str;
payRequest.timeStamp = time_stamp.intValue;
payRequest.package = WX_PAY_PACKAGE;//???? //第二次签名参数列表
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: WX_PAY_APP_ID forKey:@"appid"];
[signParams setObject: nonce_str forKey:@"noncestr"];
[signParams setObject: WX_PAY_PACKAGE forKey:@"package"];
[signParams setObject: WX_PAY_PARTNER_ID forKey:@"partnerid"];
[signParams setObject: time_stamp forKey:@"timestamp"];
[signParams setObject: object.wxPrePayID forKey:@"prepayid"];
//[signParams setObject: @"MD5" forKey:@"signType"];
//生成签名
NSString *sign = [self createMd5Sign:signParams];
payRequest.sign = sign;//????
BOOL status = [WXApi sendReq:payRequest];
if (!status) {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_REQUEST code:NYPaymentErrorCodeWeChatRequestError userInfo:@{NSLocalizedDescriptionKey:@"支付请求失败!"}];
if (completion != nil) {
completion(error, nil, nil);
}
} else {
if (completion != nil) {
completion(nil, nil, nil);
}
}
}
} - (void)sendWeChatPrePayRequestWithOrderID:(NSString *)orderID orderTitle:(NSString *)orderTitle price:(NSString *)price completion:(NYPaymentComletion)completion {
self.completion = completion;
NSMutableDictionary *preOrder = [NSMutableDictionary dictionary];
srand( (unsigned)time() );
NSString *noncestr = [NSString stringWithFormat:@"%d", rand()]; [preOrder setObject: WX_PAY_APP_ID forKey:@"appid"]; //开放平台appid
[preOrder setObject: WX_PAY_PARTNER_ID forKey:@"mch_id"]; //商户号
[preOrder setObject: WX_PAY_DEVICE_INFO forKey:@"device_info"]; //支付设备号或门店号
[preOrder setObject: noncestr forKey:@"nonce_str"]; //随机串
[preOrder setObject: @"APP" forKey:@"trade_type"]; //支付类型,固定为APP
[preOrder setObject: orderTitle forKey:@"body"]; //订单描述,展示给用户
[preOrder setObject: WX_PAY_NOTIFY_URL forKey:@"notify_url"]; //支付结果异步通知
[preOrder setObject: orderID forKey:@"out_trade_no"];//商户订单号
[preOrder setObject: WX_PAY_BILL_CREATE_IP forKey:@"spbill_create_ip"];//发器支付的机器ip
[preOrder setObject: price forKey:@"total_fee"]; //订单金额,单位为分 NSString *prePayID = [self getPrePayIDWithPrePayOrder:preOrder];
if (prePayID.length != ) { NSString *package, *time_stamp, *nonce_str;
//设置支付参数
time_t now;
time(&now);
time_stamp = [NSString stringWithFormat:@"%ld", now];
nonce_str = [NYWXPayUtility md5:time_stamp];
//重新按提交格式组包,微信客户端暂只支持package=Sign=WXPay格式,须考虑升级后支持携带package具体参数的情况
//package = [NSString stringWithFormat:@"Sign=%@",package];
package = WX_PAY_PACKAGE;
//第二次签名参数列表
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: WX_PAY_APP_ID forKey:@"appid"];
[signParams setObject: nonce_str forKey:@"noncestr"];
[signParams setObject: package forKey:@"package"];
[signParams setObject: WX_PAY_PARTNER_ID forKey:@"partnerid"];
[signParams setObject: time_stamp forKey:@"timestamp"];
[signParams setObject: prePayID forKey:@"prepayid"];
//[signParams setObject: @"MD5" forKey:@"signType"];
//生成签名
NSString *sign = [self createMd5Sign:signParams]; //添加签名
[signParams setObject: sign forKey:@"sign"];
if (self.completion != nil) {
self.completion(nil, nil, signParams);
} } else {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_PREPAYID code:NYPaymentErrorCodeWeChatGetPrePayIDFailed userInfo:@{NSLocalizedDescriptionKey:@"获取prepayid失败!\n"}];
if (self.completion != nil) {
self.completion(error, preOrder, nil);
}
} } - (NSString *)getPrePayIDWithPrePayOrder:(NSMutableDictionary *)preOrder {
NSString *prePayID = nil;
NSString *packageSign = [self packageSign:preOrder]; NSData *response = [NYWXPayUtility postSynchronousRequestWithURL:WX_PAY_UNIFIEDORDER_API httpBody:packageSign];
NYXMLParser *xml = [[NYXMLParser alloc] init];
[xml parseData:response];
NSMutableDictionary *dictionary = [xml dictionary];
//判断返回
NSString *return_code = [dictionary objectForKey:@"return_code"];
NSString *return_msg = [dictionary objectForKey:@"return_msg"];
NSString *result_code = [dictionary objectForKey:@"result_code"];
NSString *err_code = [dictionary objectForKey:@"err_code"];
NSString *err_code_des = [dictionary objectForKey:@"err_code_des"];
if ( [return_code isEqualToString:@"SUCCESS"] ) {
//生成返回数据的签名
NSString *sign = [self createMd5Sign:dictionary ];
NSString *send_sign =[dictionary objectForKey:@"sign"] ; //验证签名正确性
if( [sign isEqualToString:send_sign]){
if( [result_code isEqualToString:@"SUCCESS"]) {
//验证业务处理状态
prePayID = [dictionary objectForKey:@"prepay_id"];
return_code = ;
// if (self.completion != nil) {
// self.completion(nil, nil, nil);
// }
// [debugInfo appendFormat:@"获取预支付交易标示成功!\n"];
} else {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_RESULT_FAIL code:NYPaymentErrorCodeWeChatResultCodeFail userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat:@"获得prepayid失败, %@, %@", err_code, err_code_des]}];
if (self.completion != nil) {
self.completion(error, nil, nil);
}
}
} else {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_SIGN code:NYPaymentErrorCodeWeChatSignVerifyError userInfo:@{NSLocalizedDescriptionKey:[NSString stringWithFormat: @"服务器返回签名验证错误!!!\n返回信息:%@", return_msg]}];
if (self.completion != nil) {
self.completion(error, send_sign, nil);
}
// last_errcode = 1;
// [debugInfo appendFormat:@"gen_sign=%@\n _sign=%@\n",sign,send_sign];
// [debugInfo appendFormat:@"服务器返回签名验证错误!!!\n"]; }
} else {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_SERVER code:NYPaymentErrorCodeWeChatSignVerifyError userInfo:@{NSLocalizedDescriptionKey: [NSString stringWithFormat: @"请求接口返回错误!!!\n返回信息:%@", return_msg]}];
if (self.completion != nil) {
self.completion(error, packageSign, nil);
} // last_errcode = 2;
// [debugInfo appendFormat:@"接口返回错误!!!\n"];
}
return prePayID;
}
//获取package带参数的签名包
- (NSString *)packageSign:(NSMutableDictionary *)packageParams {
NSString *sign;
NSMutableString *reqPars = [NSMutableString string];
//生成签名
sign = [self createMd5Sign:packageParams];
//生成xml的package
NSArray *keys = [packageParams allKeys];
NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
[reqPars appendString:@"<xml>\n"];
for (NSString *categoryId in sortedArray) {
[reqPars appendFormat:@"<%@>%@</%@>\n", categoryId, [packageParams objectForKey:categoryId],categoryId];
}
[reqPars appendFormat:@"<sign>%@</sign>\n</xml>", sign]; return [NSString stringWithString:reqPars];
}
/**
* 具体签名加密方法见 https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=4_3
**/
- (NSString *)createMd5Sign:(NSMutableDictionary*)dict {
NSMutableString *contentString =[NSMutableString string];
NSArray *keys = [dict allKeys];
//按字母顺序排序
NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2 options:NSNumericSearch];
}];
//拼接字符串
for (NSString *categoryId in sortedArray) {
if ( ![[dict objectForKey:categoryId] isEqualToString:@""]
&& ![categoryId isEqualToString:@"sign"]
&& ![categoryId isEqualToString:@"key"]
)
{
[contentString appendFormat:@"%@=%@&", categoryId, [dict objectForKey:categoryId]];
} }
//添加key字段
[contentString appendFormat:@"key=%@", WX_PAY_API_KEY];
//得到MD5 sign签名
NSString *md5Sign =[NYWXPayUtility md5:contentString]; return md5Sign;
} - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
BOOL result = NO;
if ([url.scheme isEqualToString:[NSString stringWithFormat:@"%@", WX_PAY_APP_ID]]) {
result = [WXApi handleOpenURL:url delegate:self];
}
return result;
} - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
BOOL result = NO;
if ([url.scheme isEqualToString:[NSString stringWithFormat:@"%@", WX_PAY_APP_ID]]) {
result = [WXApi handleOpenURL:url delegate:self];
}
return result;
} #pragma mark - wechat delegate - (void)onReq:(BaseReq *)req { } - (void)onResp:(BaseResp *)resp {
if ([resp isKindOfClass:[PayResp class]]) {
PayResp *paymentResponse = (PayResp *)resp;
switch (paymentResponse.errCode) {
case : { break;
}
case -: {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_PAYFAILED code:NYPaymentErrorCodeWeChatPayFailed userInfo:@{NSLocalizedDescriptionKey:@"支付失败,可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等"}];
if (self.completion != nil) {
self.completion(error, nil, nil);
}
break;
}
case -: {
NSError *error = [NSError errorWithDomain:PAYMENT_ERROR_DOMAIN_WX_PAYCANCELED code:NYPaymentErrorCodeWeChatPayCanceled userInfo:@{NSLocalizedDescriptionKey:@"用户取消支付"}];
if (self.completion != nil) {
self.completion(error, nil, nil);
}
break;
}
default:
break;
}
}
} @end
iOS开发总结--三方平台开发之微信支付的更多相关文章
- iOS开发总结--三方平台开发之分享
1.前言 在公司参与了多个应用三方平台的开发,涉及微信.微博.QQ.Facebook.meetup等,总结一下一般的接入三方平台SDK方法. 2.接入三方SDK 任何应用要接入三方平台,都需要在该平台 ...
- 微信公众平台开发教程--方培工作室,PHP语言版本
准备工作 微信公众平台的注册 介绍如何注册一个微信公众账号. 入门教程 微信公众平台开发入门教程 内容:1.申请SAE作为服务器; 2.启用开发模式; 3.微信公众平台PHP SDK; 4.接收发送消 ...
- C#开发微信门户及应用(32)--微信支付接入和API封装使用
在微信的应用上,微信支付是一个比较有用的部分,但也是比较复杂的技术要点,在微商大行其道的年代,自己的商店没有增加微信支付好像也说不过去,微信支付旨在为广大微信用户及商户提供更优质的支付服务,微信的支付 ...
- NET微信公众号开发-5.0微信支付(待测试)
开发前准备. 1.0微信支付官方开发者文档 2.0官方demo下载 我们用c#所以选择.net版本 不过这个官方的demo根本跑步起来 3.0官方demo运行起来解决方案 4.0微信支付官方.net版 ...
- PHP微信支付开发实例
这篇文章主要为大家详细介绍了PHP微信支付开发过程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 PHP微信支付开发过程,分享给大家,供大家参考,具体内容如下 1.开发环境 Thinkphp 3. ...
- .NET微信公众号开发-5.0微信支付
一.前言 在开始做这个功能之前,我们要做的第一件事情就是思考,如何做这个微信支付,从哪里开始,从哪里入手,官方的sdk说明什么的,有没有什么官方的demo,还有就是老板给我的一些资料齐全不,那些要申请 ...
- php微信支付(仅pc端扫码支付模式二)详细步骤.----仅适合第一次做微信开发的程序员
本人最近做了微信支付开发,是第一次接触.其中走了很多弯路,遇到的问题也很多.为了让和我一样的新人不再遇到类似的问题,我把我的开发步骤和问题写出来,以供参考. 开发时间是2016/8/10,所以微信支付 ...
- php微信支付(仅Jsapi支付)详细步骤.----仅适合第一次做微信开发的程序员
本人最近做了微信支付开发,是第一次接触.其中走了很多弯路,遇到的问题也很多.为了让和我一样的新人不再遇到类似的问题,我把我的开发步骤和问题写出来,以供参考. 开发时间是2016/8/2,所以微信支付的 ...
- PHP后台支付的开发:微信支付和支付宝支付
关于支付的流程之类的就不做解释,大家可以自行搜索! 微信支付 项目前提:本人用的是tp框架,PHP语言下载到微信平台提供的微信支付接口文件,放在了tp第三方类库vendor,命名为WxpayAPI, ...
随机推荐
- UUID含义及ubuntu配置系统默认JDK
UUID含义是通用唯一识别码(Universally Unique Identifier) GUID是一个128位长的数字,一般用16进制表示.算法的核心思想是结合机器的网卡.当地时间.一个随即数来生 ...
- 2018.10.19 bzoj1057: [ZJOI2007]棋盘制作(悬线法)
传送门 悬线法板题. 如果只求最大矩形面积那么跟玉蟾宫是一道题. 现在要求最大正方形面积. 所以每次更新最大矩形面积时用矩形宽的平方更新一下正方形答案就行了. 代码: #include<bits ...
- 2018.10.12 NOIP模拟 棋盘问题(切比雪夫距离)
传送门 貌似是防ak题? 考试的时候想到了做四次cdqcdqcdq于是给自己多套了一个lognlognlogn结果还MLEMLEMLE 0分.(记得最后5分钟调出来的时候是那么的欣喜 下来发现并不需要 ...
- 2018.10.02 NOIP模拟 序列维护(线段树+广义欧拉定理)
传送门 一道比较好的线段树. 考试时线性筛打错了于是弃疗. 60分暴力中有20分的快速幂乘爆了于是最后40分滚粗. 正解并不难想. 每次区间加打懒标记就行了. 区间查询要用到广义欧拉定理. 我们会发现 ...
- Series转成list
直接list(series)就可以的 最佳的方式是将列表转换成Python中的科学计算包numpy包的array类型,再进行加减. 1 2 3 4 import numpy as np a = np. ...
- java梳理-序列化与反序列化
一背景: 之前笔记关于rpc框架介绍中,提到为了调用远程服务,需要再确定消息结构后考虑序列化与反序列化,序列化主要是把对象转换成二进制码便于网络传输,反序列化就是相反的,主要目的是生成对象便于后续处理 ...
- Android的方法数超过65535问题
Under the Hood: Dalvik patch for Facebook for Android 先来看一段中文内容 Hack Dalvik VM解决Android 2.3 DEX/Line ...
- hdu 1300 Deck
题目 分析:对于n张卡片的最佳摆法,我们只需要在n-1张卡片的摆法下面加一张边缘与桌檐重合的卡片,并将所有卡片一起向桌檐外移动.对于一种最佳摆法,其中心一定在桌檐上,所以一定符合杠杆原理,支点是桌檐. ...
- DBCC--常用跟踪标记
使用DBCC TRACEON 和DBCC TRACEOFF来打开和关闭跟踪标记 使用DBCC TRACESTATUS来查看所有打开的跟踪标记 --260:打印关于扩展存储过程动态链接库的版本信息 -- ...
- C#线程运用基础
ThreadStart ts=new ThreadStart(a.f);//ThreadStart 是一个委托,用以关联a.f方法Thread th=new Thread (ts);//Thread是 ...